#include "TestClientReceiveLoop.h"
#include "Network.h"

#include <iostream>
#include "conio.h"

class PlayerClientSide;

PlayerClientSide *me;

class PlayerClientSide
{
public:
	PlayerClientSide() {
		_player = NULL;
	}
	PlayerClientSide(PlayerMessage *player)
	{
		_player = player;
	}

	void draw()
	{
		// draw player
		std::cout << "  " << _player->_id._machine << ":" << _player->_id._object;
		if (this == me)
			std::cout << "(me)";
		std::cout << ": position=(" <<
			_player->positionX << ", " <<
			_player->positionY << ")" << std::endl;
	}

	PlayerMessage *_player;
};

std::map<ID, PlayerClientSide> playerMap;
boost::mutex playerMapMutex;

class PlayerListener: public MessageHandler
{
	public:
		virtual void onReceivePlayerMessage(PlayerMessage *player, boost::asio::ip::udp::endpoint endpoint) {
			boost::mutex::scoped_lock lock(playerMapMutex);
			// check if this message is received for the first time
			if (playerMap[player->_id]._player == NULL)
			{
				// allocate all client side objects
				playerMap[player->_id] = PlayerClientSide(player);
				// check if this player object is the body we are controlling
				if (player->machineID == Object::getMachineID())
					me = &playerMap[player->_id];
			}
		}
		virtual void onReceiveItemMessage(ItemMessage *receivedMessage, boost::asio::ip::udp::endpoint endpoint) {
			// not implemented in this test
		}
		virtual void onReceiveControlMessage(ControlMessage *control, boost::asio::ip::udp::endpoint senderEndpoint)
		{
			// not needed by the client
		}
};


void TestClientReceiveLoop::run()
{
	int frame = 0;
	Object::init(false);
	char *testServerName = "127.0.0.1";
	boost::asio::ip::udp::endpoint testServer = Network::getEndpoint(testServerName);
	Network::addReceiverEndpoint(testServer);
	try
	{
		PlayerListener playerListener;
		Object::setMessageHandler(&playerListener);
		ControlMessage *control = Object::createControlMessage();
		Object::sendMessageNow(control);
		Object::startReceiving();

		while (!kbhit())
		{
			// handle input
			control->mouseX = rand();
			control->mouseY = rand();
			std::cout << "frame " << frame++ << std::endl;
			std::cout << "  mouse=(" <<
				control->mouseX << ", " <<
				control->mouseY << ")" << std::endl;
			// send input to the server
			Object::sendMessageNow(control);

			// handle incomming messages
			Object::receiveMessage();
			// iterate through players for drawing
			std::map<ID, PlayerClientSide>::iterator playerIt;
			for (playerIt = playerMap.begin(); playerIt != playerMap.end(); playerIt++)
			{
				playerIt->second.draw();
			}

			boost::posix_time::milliseconds waitTime(1000);
			boost::this_thread::sleep(waitTime);
		}
		Object::stopReceiving();
	}
	catch (...)
	{
		std::cout << "failed to reach server at " << testServer << std::endl;
	}


	return;
}
